package com.healthcloud.utils;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.jsoup.helper.StringUtil;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期处理
 * Created by yu on 2017/6/6.
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    public final static String DATE_PATTERN = "yyyy-MM-dd";
    public final static String TIME_PATTERN = "HH:mm:ss";
    public final static String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    private static SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_PATTERN);
    private static SimpleDateFormat timeFormat = new SimpleDateFormat(TIME_PATTERN);
    private static SimpleDateFormat dateTimeFormat = new SimpleDateFormat(DATETIME_PATTERN);

    private static java.time.format.DateTimeFormatter localDateFormat = java.time.format.DateTimeFormatter.ofPattern(DATE_PATTERN);
    private static java.time.format.DateTimeFormatter localTimeFormat = java.time.format.DateTimeFormatter.ofPattern(TIME_PATTERN);
    private static java.time.format.DateTimeFormatter localDateTimeFormat = java.time.format.DateTimeFormatter.ofPattern(DATETIME_PATTERN);

    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    private long lNow = System.currentTimeMillis();
    private Calendar cNow = Calendar.getInstance();
    private Date dNow = new Date(lNow);
    private Timestamp tNow = new Timestamp(lNow);
    private java.sql.Date today = new java.sql.Date(lNow);
    private java.sql.Time now = new java.sql.Time(lNow);

    /**
     * 默认构造方法
     */
    public DateUtils() {

    }

    /*
     * private DateTime(long lNow, Calendar cNow, Date dNow, Timestamp tNow,
     * java.sql.Date today, Time now) { this.lNow = lNow; this.cNow = cNow;
     * this.dNow = dNow; this.tNow = tNow; this.today = today; this.now = now; }
     */

    /**
     * 得到年
     *
     * @param c
     * @return
     */
    public static int getYear(Calendar c) {
        if (c != null) {
            return c.get(Calendar.YEAR);
        } else {
            return Calendar.getInstance().get(Calendar.YEAR);
        }
    }

    /**
     * 得到月份 注意，这里的月份依然是从0开始的
     *
     * @param c
     * @return
     */
    public static int getMonth(Calendar c) {
        if (c != null) {
            return c.get(Calendar.MONTH);
        } else {
            return Calendar.getInstance().get(Calendar.MONTH);
        }
    }

    /**
     * 得到日期
     *
     * @param c
     * @return
     */
    public static int getDate(Calendar c) {
        if (c != null) {
            return c.get(Calendar.DATE);
        } else {
            return Calendar.getInstance().get(Calendar.DATE);
        }
    }

    /**
     * 得到星期
     *
     * @param c
     * @return
     */
    public static int getDay(Calendar c) {
        if (c != null) {
            return c.get(Calendar.DAY_OF_WEEK);
        } else {
            return Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
        }
    }

    /**
     * 得到小时
     *
     * @param c
     * @return
     */
    public static int getHour(Calendar c) {
        if (c != null) {
            return c.get(Calendar.HOUR);
        } else {
            return Calendar.getInstance().get(Calendar.HOUR);
        }
    }

    /**
     * 得到分钟
     *
     * @param c
     * @return
     */
    public static int getMinute(Calendar c) {
        if (c != null) {
            return c.get(Calendar.MINUTE);
        } else {
            return Calendar.getInstance().get(Calendar.MINUTE);
        }
    }

    /**
     * 得到秒
     *
     * @param c
     * @return
     */
    public static int getSecond(Calendar c) {
        if (c != null) {
            return c.get(Calendar.SECOND);
        } else {
            return Calendar.getInstance().get(Calendar.SECOND);
        }
    }

    /**
     * 得到指定或者当前时间前n天的Calendar
     *
     * @param c
     * @param n
     * @return
     */
    public static Calendar beforeNDays(Calendar c, int n) {
        // 偏移量，给定n天的毫秒数
        long offset = (long) n * 24 * 60 * 60 * 1000;
        Calendar calendar = null;
        if (c != null) {
            calendar = c;
        } else {
            calendar = Calendar.getInstance();
        }

        calendar.setTimeInMillis(calendar.getTimeInMillis() - offset);
        return calendar;
    }

    /**
     * 得到指定或者当前时间后n天的Calendar
     *
     * @param c
     * @param n
     * @return
     */
    public static Calendar afterNDays(Calendar c, int n) {
        // 偏移量，给定n天的毫秒数
        long offset = (long) n * 24 * 60 * 60 * 1000;
        Calendar calendar = null;
        if (c != null) {
            calendar = c;
        } else {
            calendar = Calendar.getInstance();
        }

        calendar.setTimeInMillis(calendar.getTimeInMillis() + offset);
        return calendar;
    }

    /**
     * 昨天
     *
     * @param c
     * @return
     */
    public static Calendar yesterday(Calendar c) {
        long offset = 1 * 24 * 60 * 60 * 1000;
        Calendar calendar = null;
        if (c != null) {
            calendar = c;
        } else {
            calendar = Calendar.getInstance();
        }

        calendar.setTimeInMillis(calendar.getTimeInMillis() - offset);
        return calendar;
    }

    /**
     * 明天
     *
     * @param c
     * @return
     */
    public static Calendar tomorrow(Calendar c) {
        long offset = 1 * 24 * 60 * 60 * 1000;
        Calendar calendar = null;
        if (c != null) {
            calendar = c;
        } else {
            calendar = Calendar.getInstance();
        }

        calendar.setTimeInMillis(calendar.getTimeInMillis() + offset);
        return calendar;
    }

    /**
     * 得到指定或者当前时间前offset毫秒的Calendar
     *
     * @param c
     * @param offset
     * @return
     */
    public static Calendar before(Calendar c, long offset) {
        Calendar calendar = null;
        if (c != null) {
            calendar = c;
        } else {
            calendar = Calendar.getInstance();
        }

        calendar.setTimeInMillis(calendar.getTimeInMillis() - offset);
        return calendar;
    }

    /**
     * 得到指定或者当前时间前offset毫秒的Calendar
     *
     * @param c
     * @param offset
     * @return
     */
    public static Calendar after(Calendar c, long offset) {
        Calendar calendar = null;
        if (c != null) {
            calendar = c;
        } else {
            calendar = Calendar.getInstance();
        }

        calendar.setTimeInMillis(calendar.getTimeInMillis() - offset);
        return calendar;
    }

    /**
     * 字符串转换成日期
     *
     * @param str,pattern
     * @return date
     */
    public static Date strToDate(String str, String pattern) {
        Date date = null;
        try {
            if (StringUtil.isBlank(str)) {
                date = new Date();
            } else {
                if (StringUtil.isBlank(pattern)) {
                    pattern = "yyyy-MM-dd HH:mm:ss";
                } else {
                }
                SimpleDateFormat format = new SimpleDateFormat(pattern);
                date = format.parse(str);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 日期格式化
     *
     * @param c
     * @param pattern
     * @return
     */
    public static String format(Calendar c, String pattern) {
        Calendar calendar = null;
        if (c != null) {
            calendar = c;
        } else {
            calendar = Calendar.getInstance();
        }
        if (pattern == null || pattern.equals("")) {
            pattern = "yyyy年MM月dd日 HH:mm:ss";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(calendar.getTime());
    }

    /**
     * Date类型转换到Calendar类型
     *
     * @param d
     * @return
     */
    public static Calendar Date2Calendar(Date d) {
        Calendar c = Calendar.getInstance();
        c.setTime(d);
        return c;
    }

    /**
     * Calendar类型转换到Date类型
     *
     * @param c
     * @return
     */
    public static Date Calendar2Date(Calendar c) {
        return c.getTime();
    }

    /**
     * Date类型转换到Timestamp类型
     *
     * @param d
     * @return
     */
    public static Timestamp Date2Timestamp(Date d) {
        return new Timestamp(d.getTime());
    }

    /**
     * Calendar类型转换到Timestamp类型
     *
     * @param c
     * @return
     */
    public static Timestamp Calendar2Timestamp(Calendar c) {
        return new Timestamp(c.getTimeInMillis());
    }

    /**
     * Timestamp类型转换到Calendar类型
     *
     * @param ts
     * @return
     */
    public static Calendar Timestamp2Calendar(Timestamp ts) {
        Calendar c = Calendar.getInstance();
        c.setTime(ts);
        return c;
    }

    /**
     * 得到当前时间的字符串表示 格式2010-02-02 12:12:12
     *
     * @return
     */
    public static String getTimeString() {
        return format(Calendar.getInstance(), "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 标准日期格式字符串解析成Calendar对象
     *
     * @param s
     * @return
     */
    public static Calendar pars2Calender(String s) {
        Timestamp ts = Timestamp.valueOf(s);
        return Timestamp2Calendar(ts);
    }

    /**
     * 根据生日 计算年龄
     *
     * @param birthDay(生日)
     * @return
     * @throws Exception
     */
    public static String getAge(Date birthDay) throws Exception {
        Calendar cal = Calendar.getInstance();

        if (cal.before(birthDay)) {
            throw new IllegalArgumentException(
                    "The birthDay is before Now.It's unbelievable!");
        }
        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH) + 1;
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);

        cal.setTime(birthDay);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);

        int age = yearNow - yearBirth;

        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                //monthNow==monthBirth
                if (dayOfMonthNow < dayOfMonthBirth) {
                    age--;
                }
            } else {
                //monthNow>monthBirth
                age--;
            }
        }

        return age + "";
    }

    /**
     * DateTime转String
     *
     * @param dt
     * @param pattern （格式：dd-MM-yyyy HH:mm:ss）
     * @return String
     */
    public static String Datetime2Str(DateTime dt, String pattern) {
        if (dt != null) {
            if (StringUtils.isBlank(pattern)) {
                return dt.toString("dd-MM-yyyy HH:mm:ss");
            } else {
                return dt.toString(pattern);
            }
        } else {
            DateTime dt1 = new DateTime();
            return dt1.toString();
        }
    }

    /**
     * String转DateTime
     *
     * @param dt      时间字符串
     * @param pattern 格式类型
     * @return
     */
    public static DateTime String2Datetime(String dt, String pattern) {
        if (StringUtils.isBlank(dt)) {
            return new DateTime();
        } else {
            DateTimeFormatter format = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
            if (StringUtils.isBlank(pattern)) {
                return DateTime.parse(dt, format);
            } else {
                format = DateTimeFormat.forPattern(pattern);
                return DateTime.parse(dt, format);
            }
        }
    }

    /**
     * 增加一年
     *
     * @param date
     * @return
     */
    public static Date addYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, 1);
        return calendar.getTime();
    }

    /**
     * 通过时间秒毫秒数判断两个时间的间隔
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int difDays(Date date1, Date date2) {
        int days = (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));
        return days;
    }

    /**
     * 根据参数返回日期
     *
     * @param date
     * @return
     */
    public static String beforeDay(String date) {
        if (StringUtils.isEmpty(date)) {
            return null;
        }
        switch (date) {
            case "now":
                return getDay(Calendar.DATE, 0);
            case "week":
                return getDay(Calendar.DATE, -7);
            case "month":
                return getDay(Calendar.MONTH, -1);
            case "quarter":
                return getDay(Calendar.MONTH, -3);
            case "year":
                return getDay(Calendar.YEAR, -1);
            default:
                return null;
        }
    }

    /**
     * 获得日期
     *
     * @param field
     * @param amount
     * @return
     */
    public static String getDay(int field, int amount) {
        SimpleDateFormat format = new SimpleDateFormat(DATE_PATTERN);
        Calendar c = Calendar.getInstance();

        //过去七天
        c.setTime(new Date());
        c.add(field, amount);
        Date d = c.getTime();
        String day = format.format(d);
        return day;
    }

    // ================以下是get和set方法=========================//

    public long getLNow() {
        return lNow;
    }

    public void setLNow(long now) {
        lNow = now;
    }

    public Calendar getCNow() {
        return cNow;
    }

    public void setCNow(Calendar now) {
        cNow = now;
    }

    public Date getDNow() {
        return dNow;
    }

    public void setDNow(Date now) {
        dNow = now;
    }

    public Timestamp getTNow() {
        return tNow;
    }

    public void setTNow(Timestamp now) {
        tNow = now;
    }

    public java.sql.Date getToday() {
        return today;
    }

    public void setToday(java.sql.Date today) {
        this.today = today;
    }

    public java.sql.Time getNow() {
        return now;
    }

    public void setNow(java.sql.Time now) {
        this.now = now;
    }

    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    public static final String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }


    /**
     * String → LocalDateTime
     */
    public static java.time.LocalDateTime toLocalDateTime(String dateTimeStr) {
        return java.time.LocalDateTime.parse(dateTimeStr, localDateTimeFormat);
    }

    /**
     * LocalDateTime → String
     */
    public static String toLocalDateTimeStr(java.time.LocalDateTime time, String pattern) {
        return java.time.format.DateTimeFormatter.ofPattern(pattern).format(time);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

    }
    public static LocalDate localDateFromDate(Date date) {

        // 将Date转换为Instant
        Instant instant = date.toInstant();

        // 由于Instant是UTC时间，我们需要指定时区转换为LocalDateTime
        ZoneId zoneId = ZoneId.systemDefault(); // 获取系统默认时区
        ZonedDateTime zonedDate = instant.atZone(zoneId);

        // 最后，从ZonedDateTime获取LocalDateTime
        return zonedDate.toLocalDate();
    }

    /**
     * 获取前i年的开始时间
     *
     * @param date
     * @param i
     * @return
     */
    public static Date getPreviousStartOfYear(Date date, int i) {
        // 获取当前日期
        LocalDate currentDate = localDateFromDate(date);
        // 获取前一年的第一天
        LocalDate startOfYear = currentDate.minusYears(i).with(TemporalAdjusters.firstDayOfYear());
        // 如果需要包含具体时间（如00:00:00和23:59:59），可以转换为LocalDateTime
        LocalDateTime startDateTime = startOfYear.atStartOfDay();
        return dateFromLocalDateTime(startDateTime);
    }
    public static Date dateFromLocalDateTime(LocalDateTime localDateTime) {

        // 获取系统默认的时区
        ZoneId zoneId = ZoneId.systemDefault();

        // 将LocalDateTime转换为ZonedDateTime，指定时区
        ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);

        // 从ZonedDateTime获取Instant，这是一个全局统一的UTC时间
        Instant instant = zonedDateTime.toInstant();

        // 最后，使用Date.from()方法将Instant转换为Date
        return Date.from(instant);
    }
}